﻿using Servo_Tool.entity;
using Servo_Tool.domain;
using Servo_Tool.dal;
using System;
using Servo_Tool.cache;

namespace Servo_Tool.service
{
    public class FuncServiceImpl : IFuncService
    {
        public ResultData_FUNC ExecFunction(string funcName, string param)
        {
            //初始化过程相关的参数
            ResultData_FUNC result = new ResultData_FUNC();
            //根据传入的参数获取对应的站台编号
            if (!GlobalCachePool.single_plcItem_dict.TryGetValue(param, out PlcItemEntity item))
            {
                result.Code = "123";
                result.Msg = $"信号点[{param}]未在[PLC_ITEM]表中配置!]";
                return result;
            }

            return CreateAgvTask(item);
        }

        /// <summary>
        /// 根据站点生成对应的AGV搬送任务
        /// 1.原材料供应（隔套、垫片、卡簧、密封件）
        /// 2.空托盘供应（成品下料站台）
        /// 3.成品下料接送（成品下料站台）
        /// </summary>
        /// <param name="stnNo"></param>
        /// <param name="code"></param>
        /// <param name="msg"></param>
        public ResultData_FUNC CreateAgvTask(PlcItemEntity item)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };
            //1.获取是哪个站点触发了请求(成品站台与其他站台存在不同)
            string stnNo = item.STN_NO;

            LogEntity logEntity = new LogEntity
            {
                WORK_NAME = "[流程-0]叫料请求-RT",
                WORK_PROC = "FuncServiceImpl.CreateAgvTask",
                CONT_NO = stnNo,
                WORK_SEC = 1,
                CREATOR = 1001,
                CREATOR_NAME = "WCS系统",
                CREATE_DATE = DateTime.Now
            };

            //1.根据站点在[wcs_stn_mapping]表中匹配所需的物料类别
            string stnSql = $"select * from wcs_stn_mapping where wcs_station='{stnNo}' limit 1";
            StnMapEntity stnEntity = DBFactory.QueryFirst<StnMapEntity>(stnSql);
            if (stnEntity == null)
            {
                resultData.Code = "404";
                resultData.Msg = $"站台[{stnNo}]未在[wcs_stn_mapping]中进行配置!";
                DBFactory.Insert2WorkLog(logEntity);
                return resultData;
            }
            //如果站台标识为已使用,说明需要先将空托盘搬出
            if ("ok".Equals(stnNo))
            {
                resultData = CreateAgvTaskByOk(stnEntity);
            }
            else
            {
                resultData = CreateAgvTaskByWip(stnEntity);
            }
            return resultData;
        }

        /// <summary>
        /// 成品下料逻辑
        /// 1、判断成品暂存货位是否有空闲位置可以存放
        /// 2、判断是否有空托盘能够供应
        /// 3、先生成成品下料的搬送任务
        /// 4、再生成供应空托盘的搬送任务（生成时机待确定,先按照同时生成以优先级区分一下）
        /// </summary>
        public ResultData_FUNC CreateAgvTaskByOk(StnMapEntity entity)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };
            LogEntity logEntity = new LogEntity
            {
                WORK_NAME = "[流程-1]成品下料-RT",
                WORK_PROC = "FuncServiceImpl.CreateAgvTaskByOk",
                CONT_NO = "",
                WORK_SEC = 1,
                CREATOR = 1001,
                CREATOR_NAME = "WCS系统",
                CREATE_DATE = DateTime.Now
            };

            try
            {
                //匹配可用的成品暂存货位
                string okLocateSql = $"select * from wcs_stn_mapping where station_type='ok' and status=0 limit 1";
                StnMapEntity okStnEntity = DBFactory.QueryFirst<StnMapEntity>(okLocateSql);
                if (okStnEntity == null)
                {
                    resultData.Code = "404";
                    resultData.Msg = $"库区内暂无[成品]空闲货位!请等待...";
                    //日志记录
                    return resultData;
                }

                //生成空框补充任务(库存寻找空托盘),使用字段position_type记录类型,与stnMapping中的station_type对应
                string kkSql = $"select * from wcs_stock where position_type='ok_kk' AND stock_st=0 limit 1";
                StockEntity kkStockEntity = DBFactory.QueryFirst<StockEntity>(kkSql);
                if (kkStockEntity == null)
                {
                    resultData.Code = "404";
                    resultData.Msg = $"库区中无可用空托盘补充至成品站台!请等待...";
                    //日志记录
                    return resultData;
                }

                //0.生成组号UUID
                string groupNo = Guid.NewGuid().ToString("N");

                //1.先生成成品的下料任务
                WcsTrkEntity okDownTrk = new WcsTrkEntity
                {
                    REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                    CONT_NO = DateTime.Now.ToString("yyyyMMddHHmmss"),
                    DVC_NO = "HK_AGV",
                    CONT_TYPE = "OK",
                    TRK_TYPE = "IN",
                    //下料的优先级高
                    TRK_PRTY = "2",
                    FRM_POS = entity.WCS_STATION,
                    TO_POS = okStnEntity.WCS_STATION,
                    CUR_POS = entity.WCS_STATION,
                    IS_FULL = "1",
                    GROUP_NO = groupNo,
                    CREATOR = 1001,
                    CREATE_DATE = DateTime.Now
                };

                DBFactory.Insert2WcsTrk(okDownTrk);

                //预分配空闲货位
                okStnEntity.STATUS = 1;
                okStnEntity.CONT_NO = okDownTrk.CONT_NO;
                okStnEntity.CONT_TYPE = okDownTrk.CONT_TYPE;
                DBFactory.UpdateStnMapByNo(okStnEntity);


                WcsTrkEntity kkSupplyTrk = new WcsTrkEntity
                {
                    REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                    DVC_NO = "HK_AGV",
                    CONT_NO = kkStockEntity.CONT_NO,
                    CONT_TYPE = entity.WCS_STATION.ToUpper(),
                    TRK_TYPE = "OT",
                    TRK_PRTY = "1",
                    //起始站点
                    FRM_POS = kkStockEntity.CUR_POSITION,
                    //目标站点
                    TO_POS = entity.WCS_STATION,
                    CUR_POS = kkStockEntity.CUR_POSITION,
                    IS_FULL = "0",
                    GROUP_NO = groupNo,
                    CREATOR = 1001,
                    CREATE_DATE = DateTime.Now
                };
                //插入[WCS_TRK]
                DBFactory.Insert2WcsTrk(kkSupplyTrk);

                //锁定空框库存
                kkStockEntity.LOCKED_QTY = 1;
                kkStockEntity.STOCK_ST = 1;
                kkStockEntity.UPDATE_DATE = DateTime.Now;
                DBFactory.UpdateStockById(kkStockEntity);

                resultData.Msg = $"成品站台下料请求成功!";
                resultData.Writes = entity.WMS_STATION + "=1";
                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "500";
                resultData.Msg = ex.Message;
                return resultData;
            }
        }

        /// <summary>
        /// 原料供应逻辑
        /// 1、判断该原料对应的空托盘区域是否有空闲位置可以存放空框
        /// 2、判断该原料站点是否有可用的原料库存
        /// 3、生成空托盘取出任务
        /// 4、向该原料站点供料
        /// </summary>
        /// <returns></returns>
        public ResultData_FUNC CreateAgvTaskByWip(StnMapEntity entity)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0"
            };

            try
            {
                //3.判断一下是否有可用原料库存用于供应给目标站点
                string stockSql = $"select * from wcs_stock where position_type='{entity.WCS_STATION}' AND stock_st=0 limit 1";
                StockEntity wipStockEntity = DBFactory.QueryFirst<StockEntity>(stockSql);
                if (wipStockEntity == null)
                {
                    resultData.Code = "404";
                    resultData.Msg = $"库区[{entity.WCS_STATION}]中无可用原料!请等待...";
                    //日志记录
                    return resultData;
                }

                //生成组号-UUID
                string groupNo = Guid.NewGuid().ToString("N");

                if (entity.STATUS > 0)
                {
                    //1.该原料对应的空框区信息(使用拼接方式)
                    string wip_kk = entity.WCS_STATION + "_kk";
                    //2.根据wip_kk判断是否有空闲位置
                    string kkSql = $"select * from wcs_stn_mapping where station_type='{wip_kk}' and status=0 limit 1";
                    StnMapEntity kkLocEntity = DBFactory.QueryFirst<StnMapEntity>(kkSql);
                    if (kkLocEntity == null)
                    {
                        resultData.Code = "404";
                        resultData.Msg = $"库区中无可用货位存放[{wip_kk}]!请等待...";
                        //日志记录
                        return resultData;
                    }
                    //4.先生成空托盘取走任务(优先级高)
                    WcsTrkEntity kkRemoveTrk = new WcsTrkEntity
                    {
                        REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                        DVC_NO = "HK_AGV",
                        CONT_NO = entity.CONT_NO,
                        CONT_TYPE = entity.WCS_STATION.ToUpper(),
                        TRK_TYPE = "IN",
                        TRK_PRTY = "2",
                        //起始站点
                        FRM_POS = entity.WCS_STATION,
                        //目标站点
                        TO_POS = kkLocEntity.WCS_STATION,
                        CUR_POS = entity.WCS_STATION,
                        IS_FULL = "0",
                        GROUP_NO= groupNo,
                        CREATOR = 1001,
                        CREATE_DATE = DateTime.Now
                    };
                    //插入[WCS_TRK]
                    DBFactory.Insert2WcsTrk(kkRemoveTrk);
                    //预分配空框的货位
                    kkLocEntity.STATUS = 1;
                    kkLocEntity.CONT_NO = kkRemoveTrk.CONT_NO;
                    kkLocEntity.CONT_TYPE = kkRemoveTrk.CONT_TYPE;
                    kkLocEntity.UPDATE_DATE = DateTime.Now;
                    DBFactory.UpdateStnMapByNo(kkLocEntity);
                }
                //否则直接生成供料任务
                WcsTrkEntity wipSupplyTrk = new WcsTrkEntity
                {
                    REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                    CONT_NO = wipStockEntity.CONT_NO,
                    DVC_NO = "HK_AGV",
                    CONT_TYPE = entity.WCS_STATION.ToUpper(),
                    TRK_TYPE = "OT",
                    //上料的优先级低
                    TRK_PRTY = "1",
                    FRM_POS = wipStockEntity.CUR_POSITION,
                    TO_POS = entity.WCS_STATION,
                    CUR_POS = wipStockEntity.CUR_POSITION,
                    IS_FULL = "1",
                    GROUP_NO = groupNo,
                    CREATOR = 1001,
                    CREATE_DATE = DateTime.Now
                };

                DBFactory.Insert2WcsTrk(wipSupplyTrk);

                //锁定库存
                wipStockEntity.LOCKED_QTY = 1;
                wipStockEntity.STOCK_ST = 1;
                wipStockEntity.UPDATE_DATE = DateTime.Now;
                DBFactory.UpdateStockById(wipStockEntity);

                resultData.Msg = $"站台[{entity.WCS_STATION}]上料请求应答成功!";
                resultData.Writes = entity.WMS_STATION + "=1";
                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "500";
                resultData.Msg = ex.Message;
                return resultData;
            }
        }
    }
}
